<?php
namespace core\models;
/**
 * 网页Gzip压缩输出类
 * 【注意】此类已经在全局控制器用使用，不需要在具体的控制器中处理它
 * @author ZhouHaoHua <53027327@qq.com>
 */
class Gzip{
    private $enable;						//Gzip开关
    private $ini_zlib_output_compression;	//获取zlib.output_compression配置选项的值
    private $ext_zlib_loaded;				//检查zlib扩展是否已经加载
    private $started;						//是否已经开始执行ob_start操作
    private $has_ended;						//是否已经结束输出操作
    private $gzip_level;					//gzip的压缩值

    /**
     * 网页Gzip压缩输出类
     */
    public function __construct(){
        $this->ext_zlib_loaded = extension_loaded('zlib');
        if ($this->ext_zlib_loaded && (PHP_VERSION >= '4') ) {
            $this->ini_zlib_output_compression = (int)ini_get('zlib.output_compression');
            $this->enable = true;
        }
        $this->gzip_level = 9;
    }
    /**
     * 开始资源压缩
     * 此方法放到压缩的资源前面
     */
    public function ob_start(){
        if($this->enable === true){
            if ($this->ini_zlib_output_compression < 1) {
                if (PHP_VERSION >= '4.0.4') {
                    ob_start('ob_gzhandler');
                } else {
                    ob_start();
                    ob_implicit_flush();
                }
            } else {
                ini_set('zlib.output_compression_level', $this->gzip_level);
            }
        }
        $this->started = true;
    }
    /**
     * 资源压缩输出
     */
    public function ob_output(){
        if($this->started!==true){
            throw \Z::Error('应先执行::ob_start才能执行::ob_output');
        }
        if ( $this->enable === true && ($this->ext_zlib_loaded === true) && ($this->ini_zlib_output_compression < 1) ) {
            $this->gzip_output($this->gzip_level);
        }
        $this->has_ended = true;
    }
    /**
     * gzip检查
     * @return string|false
     */
    private function check_gzip() {
        $HTTP_ACCEPT_ENCODING = $_SERVER['HTTP_ACCEPT_ENCODING'];
        if (headers_sent() || connection_aborted()) {
            //return false;
        }
        if (strpos($HTTP_ACCEPT_ENCODING, 'x-gzip') !== false) return 'x-gzip';
        if (strpos($HTTP_ACCEPT_ENCODING,'gzip') !== false) return 'gzip';
        return false;
    }
    /**
     * gzip压缩输出
     * @param int $level 压缩值9最大
     */
    private function gzip_output($level = 5) {
        $encoding = $this->check_gzip();
        if ($encoding) {
            $contents = ob_get_contents();
            ob_end_clean();

            header('Content-Encoding: ' . $encoding);

            $size = strlen($contents);
            $crc = crc32($contents);

            $contents = gzcompress($contents, $level);
            $contents = substr($contents, 0, strlen($contents) - 4);

            echo "\x1f\x8b\x08\x00\x00\x00\x00\x00";
            echo $contents;
            echo pack('V', $crc);
            echo pack('V', $size);
        } else {
            ob_end_flush();
        }
    }
}